package com.sduept.nwld.dataserver.controller.equipment.assessment;

import com.sduept.bigdata.document.entity.core.CommonDocument;
import com.sduept.bigdata.equipment.assessment.enums.ItemTypeEnum;
import com.sduept.bigdata.equipment.assessment.enums.SubStationTypeEnum;
import com.sduept.bigdata.equipment.assessment.model.standarddict.HiddenDangerLevel;
import com.sduept.bigdata.equipment.assessment.model.standardlib.StandardInspection;
import com.sduept.bigdata.equipment.assessment.model.template.AssessmentTemplate;
import com.sduept.bigdata.equipment.assessment.service.AssessmentTemplateService;
import com.sduept.bigdata.equipment.assessment.service.StandardInspectService;
import com.sduept.core.service.StandardDictService;
import com.sduept.generator.ObjectId;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.nwld.dataserver.service.equipment.assessment.TableViewModelItemViewService;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import org.primefaces.PrimeFaces;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.FileNotFoundException;
import java.util.*;

/**
 * 评价标准管理controller，对评价标准进行增删改等操作
 * @author huangyu
 * @Date 2019年8月21日
 */
@Named
@ViewScoped
public class AssessmentStandardLibController extends AbstractController {
	
	private static final long serialVersionUID = 1636505190840652638L;

	@Autowired
	private StandardInspectService service;
	@Autowired
	private AssessmentTemplateService templateService;
	@Autowired
	private TableViewModelItemViewService viewService;
	@Autowired
	private StandardDictService dictService; 
//	@Autowired
//	private DocumentContentShowService docService;
	
	private List<TableViewModelItem> selectLists = new ArrayList<>();

	/**
	 * 树的根节点
	 */
	private LibTreeNode treeRoot;
	/**
	 * 当前版本节点
	 */
	private LibTreeNode currentNode;
	/**
	 * 历史版本节点
	 */
	private LibTreeNode historyNode;

	private StandardInspection selected = null;
	private StandardInspection rootItem = null;

	private StandardInspection current = null;
	/**
	 * 选中父节点后新建子节点，为方便确定子节点的类型，将枚举类型放入list中
	 */
	private List<ItemTypeEnum> typeList;
	
	private final String currentVersion = "当前版本";
	private final String historyVersion = "历史版本";
	
	/**
	 * 当前标准的参考文档
	 */
	private Set<CommonDocument> documents = new HashSet<CommonDocument>();

	/**
	 * 风险等级
	 */
	private List<String> riskLevels;
	/**
	 * 当前节点的类型
	 */
	private String selectedNodeType = null;
	private TreeNode selectedNode;
	/**
	 * 变电站类型：智能站、常规站
	 */
	private SubStationTypeEnum[] subStationTypes = null;
	
	@PostConstruct
	public void init() {
		subStationTypes = SubStationTypeEnum.values();
		getAllRiskLevels();
		typeList = Arrays.asList(ItemTypeEnum.ROOTNAME,ItemTypeEnum.INSPECTIONPROJECT,ItemTypeEnum.INSPECTIONITME,ItemTypeEnum.INSPECTIONREQUIREMENT,ItemTypeEnum.INSPECTIONCRITERION);
		initStandardTree();
		initTable();
	}
	/**
	 * 从字典表中获取所有的风险等级，供新建标准时进行选择
	 */
	private void getAllRiskLevels() {
		try {
			List<HiddenDangerLevel> levels = dictService.findAll(HiddenDangerLevel.class);
			if(levels!=null && !levels.isEmpty())
				riskLevels=new ArrayList<String>();
			for (HiddenDangerLevel level : levels) {
				riskLevels.add(level.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("获取风险等级时出错");
		}
	}
	/**
	 * 渲染右侧表格，初次进入页面时，显示第一个
	 */
	private void initTable() {
		rootItem = null;
		if(null == selected) {
			try {
				List<StandardInspection> avaliableInspections = service.findAvailableRoot();
				if(avaliableInspections.size()>0) {
					rootItem = avaliableInspections.get(0);
				}
			} catch (Exception e) {
				addErrorMessage("获取可用版本数据过程中发生错误");
			}
		} else {
			if(selected.getItemType()==ItemTypeEnum.ROOTNAME) {
				rootItem = selected;
			} else {
				String pStandId = selected.getStandardVersion();
				rootItem = service.findById(pStandId);
			}
		}
		if(null != rootItem) {
			genDatatableList(rootItem);
		}
	}
	
	/**
	 * 根据当前选择的节点，构造右侧的列表
	 * @param stand
	 */
	private void genDatatableList(StandardInspection stand) {
		selectLists = viewService.getTableViewModelItemListByStandard(stand);
	}
	
	/**
	 * 初始化标准项目树
	 */
	private void initStandardTree() {
		treeRoot = new LibTreeNode("Root", null);
		// 当前版本节点
		currentNode = new LibTreeNode("type",currentVersion, treeRoot);
		genCurrentVersionNode();
		currentNode.setExpanded(true);
		// 历史版本节点
		historyNode = new LibTreeNode("type",historyVersion, treeRoot);
		genHistoryVersionNode();
		historyNode.setExpanded(true);
	}

	/**
	 * 生成树中的当前版本子节点
	 * @param currentNode
	 */
	private void genCurrentVersionNode() {
		try {
			// 获取可用的当前版本
			List<StandardInspection> standards = service.findAvailableRoot();
			for (StandardInspection standard : standards) {
				if(selectedNode == null) {
					new LibTreeNode(ItemTypeEnum.ROOTNAME.getValue(),standard, currentNode);
				} else {
					LibTreeNode rootNode = new LibTreeNode(ItemTypeEnum.ROOTNAME.getValue(),standard, currentNode);
					recursionGenTreeNode(rootNode);
				}
			}
		} catch (Exception e) {
			addErrorMessage("获取可用版本数据过程中发生错误");
		}
	}
	
	/**
	 * 生成树中的历史版本子节点
	 * @param historyNode
	 */
	private void genHistoryVersionNode() {
		try {
			// 获取所有不可用的根节点
			List<StandardInspection> unAvaliableStandards = service.findUnAvailableRoot();
			for (StandardInspection standard : unAvaliableStandards) {
				if(current == null) {
					new LibTreeNode(ItemTypeEnum.ROOTNAME.getValue(),standard, historyNode);
				} else {
					LibTreeNode rootNode = new LibTreeNode(ItemTypeEnum.ROOTNAME.getValue(),standard, historyNode);
					recursionGenTreeNode(rootNode);
				}
			}
		} catch (Exception e) {
			addErrorMessage("获取不可用版本数据过程中发生错误");
		}
	}
	
	/**
	 * 递归生成树的子节点
	 * @param pNode
	 */
	private void recursionGenTreeNode(TreeNode pNode) {
		StandardInspection pStand = (StandardInspection) pNode.getData();
		if(current.equals(pNode.getData())) {
			pNode.setSelected(true);
			selectedNode = pNode;
			selected = (StandardInspection) pNode.getData();
			recursionExpandParentNode(pNode);
		} else {
			List<StandardInspection> inspections = service.findByParentId(pStand.getId());
			service.sort(inspections);
			ItemTypeEnum itemType = getChildrenTypeByParent(pStand);
			if(null != itemType) {
				for (StandardInspection stand : inspections) {			
					LibTreeNode node = new LibTreeNode(itemType.getValue(),stand, pNode);
					recursionGenTreeNode(node);
				}
			}
		}
	}
	/**
	 * 递归展开树的父节点
	 * @param node
	 */
	private void recursionExpandParentNode(TreeNode node) {
		TreeNode pNode = node.getParent();
		if(pNode != null) {
			pNode.setExpanded(true);
			recursionExpandParentNode(pNode);
		}
	}
	/**
	 * 树节点展开
	 * @param event
	 */
	public void onNodeExpand(NodeExpandEvent event) {
		selectedNode = event.getTreeNode();
		selectedNode.getChildren().clear();
		if(selectedNode.getData() instanceof String) {
			String type = (String) selectedNode.getData();
			if(currentVersion.equals(type)) {
				genCurrentVersionNode();
			} else if (historyVersion.equals(type)) {
				genHistoryVersionNode();
			}
		} else if (selectedNode.getData() instanceof StandardInspection) {
			StandardInspection select = (StandardInspection) selectedNode.getData();
			List<StandardInspection> list = service.findByParentId(select.getId());
			service.sort(list);
			ItemTypeEnum type = null;
			for (StandardInspection stand : list) {			
				type = getChildrenTypeByParent(select);
				if(null != type) {
					new LibTreeNode(type.getValue(),stand, selectedNode);
				}
			}
		}
	}

	/**
	 * 根据父获取子的类型
	 * @param parent
	 * @return ItemTypeEnum
	 */
	private ItemTypeEnum getChildrenTypeByParent(StandardInspection parent) {
		if(null == parent) {
			return null;
		}
		ItemTypeEnum type = null;
		int index = typeList.indexOf(parent.getItemType());
		if((index+1) < typeList.size()) {
			type = typeList.get(index+1);
		}
		return type;
	}
	
	/**
	 * 选择树节点
	 * @param event
	 */
	public void onNodeSelect(NodeSelectEvent event) {
		selectedNode = event.getTreeNode();
		if(selectedNode.getData() instanceof StandardInspection) {
			selected = (StandardInspection) selectedNode.getData();
			// 为防止每次点击都渲染table,仅在点击根节点时才会渲染table
			if(selected.getItemType() == ItemTypeEnum.ROOTNAME) {
				genDatatableList(selected);
				rootItem = selected;
			}
		} else if (selectedNode.getData() instanceof String) {
			selected = null;
		}
	}

	/**
	 * 新建
	 */
	public void preCreate() {
		documents.clear();
		current = new StandardInspection();
		current.setId(ObjectId.get().toString());
		// 创建根节点
		if(null == selected) {
			selectedNodeType = "ROOTNAME";
			current.setStandardVersion(current.getId());
			List<StandardInspection> rootStandards = service.findByItemType(ItemTypeEnum.ROOTNAME);
			current.setNodeNo(rootStandards.size()+1+"");
			current.setNodeOrder(rootStandards.size()+1);
			current.setItemType(ItemTypeEnum.ROOTNAME);
		}
		if(null != selected) {
			current.setParent(selected);
			current.setStandardVersion(selected.getStandardVersion());
			current.setRiskLevelCondition(selected.getRiskLevelCondition());
			current.setRiskLevelRefer(selected.getRiskLevelRefer());
			current.setRiskLevel(selected.getRiskLevel());
			ItemTypeEnum type = getChildrenTypeByParent(selected);
			current.setItemType(type);
			selectedNodeType = type.getValue();
			List<StandardInspection> lt = service.findByParentId(selected.getId());
			int nodeNo = lt.size()+1;
//			if(selected.getItemType()!=ItemTypeEnum.ROOTNAME && selected.getItemType()!=ItemTypeEnum.INSPECTIONREQUIREMENT) {
			if(selected.getItemType()!=ItemTypeEnum.ROOTNAME) {
				current.setNodeNo(selected.getNodeNo()+"."+nodeNo);
			} else {
				current.setNodeNo(nodeNo+"");
			}
			current.setNodeOrder(nodeNo);
		}
		current.setUpdateTime(new Date());
	}

	/**
	 * 编辑
	 */
	public void preEdit() {
		current = selected;
		selectedNodeType = selected.getItemType().getValue();
		try {
			documents = service.findDocumentsById(current.getId());
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("获取标准的参考文档失败");
		}
	}

	/**
	 * 保存
	 */
	public void save() {
//		if(lessThanMaxScore(current)) {
			if(current.getItemType()==ItemTypeEnum.ROOTNAME) {
				// 根据根节点是否可用，修改相应的模板的可用性
				changeTemplateAvailableAccordingToStandard(current);
			} 
			service.createOrUpdate(current);
			addSuccessMessage("保存成功");
//		} else {
//			addErrorMessage("扣分总和大于最大限值，保存失败");
//		}
		initStandardTree();
		initTable();
	}

	/**
	 * 根据标准是否可用设置模板是否可用
	 * @param stand
	 */
	private void changeTemplateAvailableAccordingToStandard(StandardInspection stand) {
		String version = stand.getStandardVersion();
		Boolean available = stand.getAvailable();
		List<AssessmentTemplate> templates = templateService.findAssessmentTemplatesByStandardVersion(version);
		for (AssessmentTemplate template : templates) {
			template.setAvailable(available);
			templateService.createOrUpdate(template);
		}
	}
	
	/**
	 * 当有新的版本设置为当前版本时，将可用模板置为不可用状态，同时，将相应的模板也置为不可用
	 */
	private void changeToUnAvailable() {
		try {
			List<StandardInspection> availableStands = service.findAvailableRoot();
			if(availableStands.size()>0) {
				for (StandardInspection standard : availableStands) {
					standard.setAvailable(false);
					service.createOrUpdate(standard);
					// 将相应的模板也置为不可用
					changeTemplateAvailableAccordingToStandard(standard);
				}
			}
		} catch (Exception e) {
			addErrorMessage("获取可用版本数据过程中发生错误");
		}
	}
	/**
	 * 判断子的扣分上限之和不的大于父的扣分上限
	 */
	private boolean lessThanMaxScore(StandardInspection stand) {
		// 根据当前记录，获取其父记录
		StandardInspection pStand = stand.getParent();
		float total = stand.getDeductionCeiling();
		if(null != pStand) {
			float maxScore = pStand.getDeductionCeiling();
			List<StandardInspection> lt = service.findByParentId(pStand.getId());
			for (StandardInspection s : lt) {
				if(!s.getId().equals(stand.getId())) {
					total += s.getDeductionCeiling();
				}
			}
			if(maxScore<total) {
				return false;
			} else {
				return true;
			}
		} else {
			return true;
		}
	}
	/**
	 * 删除标准
	 */
	public void delete() {
		try {
			service.deleteById(selected.getId());
			addSuccessMessage("删除成功");
			selectedNode = null;
			selected = null;
			current = null;
			initStandardTree();
			initTable();
		} catch (Exception e) {
			PrimeFaces.current().executeScript("PF('deleteConfirmDialog').show()");
		}
	}
	/**
	 * 删除标准时，级联删除引用该标准的模板项
	 */
	public void deleteTemplateItem() {
		try {
			service.deleteAndFkTemplateitemById(selected.getId());
			addSuccessMessage("删除成功");
			selectedNode = null;
			selected = null;
			current = null;
			initStandardTree();
			initTable();
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("根据标准删除标准评价项目和与之级联的模板条目的关系时出错");
		}
	}
	
	/**
	 * 打开参考文档选择界面
	 */
	public void openReferenceDocumentsDialog() {
		Map<String,Object> options = new HashMap<String, Object>();
        options.put("resizable", false);
        options.put("draggable", false);
        options.put("modal", true);
        options.put("width", 600);
        options.put("height", 400);
        PrimeFaces.current().dialog().openDynamic("/ui/document/common_document_multiple_selector.xhtml", options, null);
	}
	/**
	 * 选中参考文档
	 * @param event
	 */
	public void onReferenceDocumentsChosen(SelectEvent event) {
		CommonDocument selectedDocument = (CommonDocument) event.getObject();
		documents.add(selectedDocument);
		current.setDocument(documents);
	}
	
	/**
	 * 移除参考文档
	 * @param doc
	 */
	public void removeDocument(CommonDocument doc) {
		try {
			documents.remove(doc);
			current.setDocument(documents);
		} catch (Exception e) {
			e.printStackTrace();
			addErrorMessage("获取标准的参考文档失败");
		}
	}
	/**
	 * 展示文档内容
	 * @param doc
	 */
	public void getDocumentContent(CommonDocument doc) {
//		try {
//			docService.getDocumentContent(doc);
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//			addErrorMessage("文件不存在，查看失败");
//		}
	}

	public List<TableViewModelItem> getSelectLists() {
		return selectLists;
	}

	public void setSelectLists(List<TableViewModelItem> selectLists) {
		this.selectLists = selectLists;
	}

	public StandardInspection getSelected() {
		return selected;
	}

	public void setSelected(StandardInspection selected) {
		this.selected = selected;
	}

	public StandardInspection getRootItem() {
		return rootItem;
	}

	public void setRootItem(StandardInspection rootItem) {
		this.rootItem = rootItem;
	}

	public StandardInspection getCurrent() {
		return current;
	}

	public void setCurrent(StandardInspection current) {
		this.current = current;
	}

	public Set<CommonDocument> getDocuments() {
		return documents;
	}

	public void setDocuments(Set<CommonDocument> documents) {
		this.documents = documents;
	}

	public List<String> getRiskLevels() {
		return riskLevels;
	}

	public void setRiskLevels(List<String> riskLevels) {
		this.riskLevels = riskLevels;
	}
	
	public String getSelectedNodeType() {
		return selectedNodeType;
	}
	
	public void setSelectedNodeType(String selectedNodeType) {
		this.selectedNodeType = selectedNodeType;
	}

	public SubStationTypeEnum[] getSubStationTypes() {
		return subStationTypes;
	}
	
	public void setSubStationTypes(SubStationTypeEnum[] subStationTypes) {
		this.subStationTypes = subStationTypes;
	}
	public TreeNode getSelectedNode() {
		return selectedNode;
	}
	public void setSelectedNode(TreeNode selectedNode) {
		this.selectedNode = selectedNode;
	}
	public LibTreeNode getTreeRoot() {
		return treeRoot;
	}
	public void setTreeRoot(LibTreeNode treeRoot) {
		this.treeRoot = treeRoot;
	}
	
}
